package eclMain;


import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;

import org.joda.time.DateTime;

/**This controls everything to do with the identity of the channel, as well as reading out new lines as they are entered.
 * All lines that have been read are kept in chatLineRecord, and can be cleared manually if necessary.
 * This object does not read files automatically. The "readAvailable()" method must be called each time you want to get new chat lines from the file.*/
public class ChatFile {
	private Path filePath = null;
	Channel channel = null;
	private long skippedChars = 0; //number of characters that have been previously read out of this file
	private long sizeAtLastRead = 0;
	
	public ChatFile(Path directory, Path fileName) throws Exception { //if something goes wrong, I need to remove this file from the master list, and I can't do that here
		Path filePath = Paths.get(directory.toAbsolutePath().toString(), fileName.getFileName().toString());
		this.filePath = filePath;
		this.channel = new Channel(null);
		ArrayList<ChatLine> header = readAvailable(15); //only read the relevant lines for the channel header; catch up later on the rest of it
		this.channel.parseHeader(header);
		if (this.channel.isChannelInitialized() == false) Notifier.errorNotify("Failed to parse header for: " + fileName.toString());
	}
	
	/**read any new lines. Method opens the file, skips to the new content, reads it, then closes the file, returning the new lines, and also adding them to the chatLineRecord.
	 * Only reads new lines if there is a difference in size from the last time this file was read, otherwise returns null.
	 * Limit is the maximum number of lines that you want to read. Enter -1 to read all available.*/
	public ArrayList<ChatLine> readAvailable(int limit) throws Exception {
		ArrayList<ChatLine> lines = new ArrayList<ChatLine>();
		
		//first, make sure that there's something to read that I haven't seen already
		if (this.sizeAtLastRead == Files.size(this.filePath)) return lines;
		
		//open the file, skip previously read characters, and read in new characters
		Charset charset = Charset.forName("UTF-16");
		BufferedReader reader = Files.newBufferedReader(filePath, charset);
		reader.skip(this.skippedChars);
		String readChars = "";
		int linesRead = 0;
		while (reader.ready() && linesRead != limit) {
			char c = (char)reader.read();
			readChars += c;
			if (c == '\n') {
				linesRead += 1;
			}
		}
		
		String[] readLines = readChars.split("\n"); //split new characters into lines
		
		//process each line for timestamp and text
		for (String strLine : readLines) {
			this.skippedChars += strLine.length() + 1; //line length + new line character
			strLine = strLine.trim();
			if (strLine.length() == 0) continue; //skip blank lines
			
			ChatLine line = new ChatLine(strLine, this.channel);
			if (line.getText() == null) {
				Notifier.errorNotify("Failed to read: \"" + strLine + "\"");
				continue; //failed to read the line, try the next one
			}
			
			if (line.getOwner() != null && line.getOwner().equals("EVE System")) { //look for a "Channel changed" line. Doing it this way makes it universal for all specific channels (I hope)
				if (line.getText().startsWith("Channel changed to Local :")) {
					String ln = line.getEntireLine().trim();
					String[] lna = ln.split(":");
					this.channel.setLocation(lna[lna.length-1].trim());
				}
				else if (line.getEntireLine().contains("EVE System > Channel changed to Corp :")) {
					//XXX: do nothing for now; later on, I need to figure out all permutations of these lines, and how they figure into tracking channels correctly
				}
			}
			else { //normal line
				lines.add(line);
			}
		}
		reader.close();
		if (lines.size() > 0) this.sizeAtLastRead = Files.size(this.filePath); //set the new size of the file
		return lines;
	}
	
	/**This method opens the file, reads to the end, and saves number of characters read, so that they can be skipped in the readAvailable() method
	 * @throws IOException */
	public void readToEoF() throws IOException {
		this.skippedChars = Files.size(filePath)/2;
	}
	
	/**Compares Session Timestamps that are embedded inside the files*/
	public boolean isMoreRecentThan(ChatFile newFile) {
		int num = this.channel.getSessionTimeStamp().getJodaTime().compareTo(newFile.channel.getSessionTimeStamp().getJodaTime());
		if (num >= 0) return true; //technically no file should ever have the same exact date, but just to be safe...
		return false;
	}
	
	/**The "listener" is the character that is recording the chatlog*/
	public boolean hasSameListener(ChatFile cFile) {
		return this.channel.getListener().equals(cFile.channel.getListener());
	}
	
	public Path getPath() {
		return this.filePath;
	}
	
	/**Returns the name parsed out from the Channel Header*/
	public String getName() {
		return this.channel.getChannelName();
	}
	
	public DateTime getCreationTime() {
		return this.channel.getSessionTimeStamp().getJodaTime();
	}
	
	public Channel getChannel() {
		return this.channel;
	}
	
	/**I should probably clean this up at some point, and make sure it's actually still relevant.*/
	public String toString() {
		return String.format("Channel Name: %s\n\tChannel Type, ID: %s, %s\n\tListener: %s\n\tTime Created: %s\n", getName(), this.channel.getChannelIDType(),
				this.channel.getChannelID(), this.channel.getListener(), this.channel.getSessionTimeStamp().toString());
	}
}
